package com.hexacta.hrs.test.architecture;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import jdepend.framework.JDepend;
import jdepend.framework.JavaPackage;
import junit.framework.TestCase;

import org.apache.commons.io.FileUtils;

/**
 * Verifies the package dependencies.
 * 
 * @see https://wiki.hexacta.com/mediawiki/index.php/hrs:KB-5
 * 
 * @author tpollak
 */
public class PackageDependenciesTestI extends TestCase {
    private JDepend engine;

    public void testModelDependencyToHibernateClasses() {
        this.assertPackageConstraint("com.hexacta", "org.vectrics.hibernate", Arrays.asList(
                "com.hexacta.hrs.spring",
                "com.hexacta.hrs.report.managers"
                ));
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        // We have to jump through some hoops to get to the 'classes' directory:
        // we know that the spring config is in the root, so we get it and go
        // one level up.
        String rootDirectory = FileUtils.toFile(this.getClass().getResource("/spring-model-config.xml"))
                .getParentFile().getAbsolutePath();

        // Setup the JDepend analysis
        this.engine = new JDepend();
        this.engine.addDirectory(rootDirectory);
        this.engine.analyze();
    }

    @Override
    protected void tearDown() throws Exception {
        this.engine = null;

        super.tearDown();
    }

    @SuppressWarnings("unchecked")
    private void assertPackageConstraint(String afferentPrefix, String expectedNotEfferent,
            Collection<String> exclusions) {
        Collection<JavaPackage> allPAckages = this.engine.getPackages();
        for (Iterator<JavaPackage> i = allPAckages.iterator(); i.hasNext();) {
            JavaPackage afferentPackage = i.next();
            String afferentPackageName = afferentPackage.getName();
            if (afferentPackageName.startsWith(afferentPrefix)
                    && !this.isInExclusionList(exclusions, afferentPackageName)) {
                JavaPackage efferentPackage = this.engine.getPackage(expectedNotEfferent);
                assertFalse(afferentPackageName + " shouldn't depend on " + efferentPackage.getName(), afferentPackage
                        .getEfferents().contains(efferentPackage));
            }
        }
    }

    private boolean isInExclusionList(Collection<String> exclusions, String afferentPackageName) {
        for (String exclusionPrefix : exclusions) {
            if (afferentPackageName.startsWith(exclusionPrefix)) {
                return true;
            }
        }
        return false;
    }

}
